package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.builder.dto.ExhibitorDTO;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.pay.dto.ApplyRefundDTO;
import com.eastfair.pay.dto.TransactionOrderDTO;
import com.eastfair.pay.enumeration.TransactionOrderOrderStatusEnum;
import com.eastfair.pay.enumeration.TransactionOrderOrderTypeEnum;
import com.eastfair.pay.enums.ApplyRefundBusinessTypeEnum;
import com.eastfair.pay.enums.RefundClassifyEnum;
import com.eastfair.projectcore.enumeration.MenuAffiliationEnum;
import com.eastfair.venueservice.dao.BondManageMapper;
import com.eastfair.venueservice.dto.BondManageDTO;
import com.eastfair.venueservice.dto.DepositWarningDTO;
import com.eastfair.venueservice.dto.ExhibitionSettlementDTO;
import com.eastfair.venueservice.entity.BondManage;
import com.eastfair.venueservice.entity.CreatCode;
import com.eastfair.venueservice.enumeration.BondManageOrderStatusEnum;
import com.eastfair.venueservice.enums.BondManagePayStatusEnum;
import com.eastfair.venueservice.enums.BondManageRefundStatus;
import com.eastfair.venueservice.enums.ServiceOrderRefundStatus;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.BondManageVO;
import com.eastfair.venueservice.vo.ExhibitionSettlementVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 保证金管理
 * </p>
 *
 * @author lyw
 * @date 2023-02-14
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class BondManageServiceImpl extends SuperServiceImpl<BondManageMapper, BondManage> implements BondManageService {

    @Value("${pay.payee.venue-manage}")
    private String venueManagePayee;

    private static final String ORDER_NUMBER_FIELD = "order_number";

    private static final int ORDER_NUMBER_LENGTH = 5;

    @Resource
    private DepositWarningService depositWarningService;

    @Resource
    private ViolationFineService violationFineService;

    @Resource
    private VenueManageTransactionOrderService venueManageTransactionOrderService;

    @Resource
    private VenueManageApplyRefundService venueManageApplyRefundService;

    @Resource
    private VenueManageUserAccountService venueManageUserAccountService;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<BondManage> modelList) {
        modelList.forEach(s -> s.setIsDeleted(BusinessConstant.YES));
        return R.successDef();
    }

    @Override
    protected R<Boolean> handlerSave(BondManage model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        if (StrUtil.isBlank(model.getPayStatus())) {
            model.setPayStatus(BondManagePayStatusEnum.UNPAY.getCode());
        }
        if (StrUtil.isBlank(model.getRefundStatus())) {
            model.setRefundStatus(BondManageRefundStatus.NO_REFUND.getCode());
        }
        return R.successDef();
    }

    public void handlerQueryParams(PageParams<BondManageDTO> pageParams) {
        if (StrUtil.isBlank(pageParams.getSort()) || StrUtil.isBlank(pageParams.getOrder())) {
            pageParams.setSort("createTime");
            pageParams.setOrder("descending");
        }
    }

    /**
     * 分页查询保证金管理列表
     *
     * @param pageParams
     * @return
     */
    @Override
    public IPage<BondManageVO> queryBondManageList(PageParams<BondManageDTO> pageParams) {
        log.info("BondManageServiceImpl +++++ queryBondManageList - 分页查询保证金管理列表 pageParams={}", JSONObject.toJSON(pageParams));
        handlerQueryParams(pageParams);
        Page<BondManage> page = pageParams.buildPage();
        BondManageDTO bondManagePageQuery = pageParams.getModel();
        QueryWrapper<BondManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BondManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .like(StrUtil.isNotBlank(bondManagePageQuery.getExhibitionManageName()), BondManage::getExhibitionManageName, bondManagePageQuery.getExhibitionManageName())
                .like(StrUtil.isNotBlank(bondManagePageQuery.getServiceProviderName()), BondManage::getServiceProviderName, bondManagePageQuery.getServiceProviderName())
                .eq(Objects.nonNull(bondManagePageQuery.getServiceProviderType()), BondManage::getServiceProviderType, bondManagePageQuery.getServiceProviderType())
                .eq(Objects.nonNull(bondManagePageQuery.getServiceProviderId()), BondManage::getServiceProviderId, bondManagePageQuery.getServiceProviderId())
                .eq(StrUtil.isNotBlank(bondManagePageQuery.getSystemScene()), BondManage::getSystemScene, bondManagePageQuery.getSystemScene())
                .eq(Objects.nonNull(bondManagePageQuery.getPayStatus()), BondManage::getPayStatus, bondManagePageQuery.getPayStatus())
                .eq(Objects.nonNull(bondManagePageQuery.getExhibitionManageId()), BondManage::getExhibitionManageId, bondManagePageQuery.getExhibitionManageId())
                .orderByDesc(BondManage::getCreateTime);
        page = page(page, queryWrapper);
        Page<BondManageVO> resultPage = ConvertUtil.convertPage(page, BondManageVO.class);
        return resultPage;
    }

    /**
     * 通过服务商id获取保证金集合
     *
     * @param exhibitorDTO
     * @return
     */
    @Override
    public List<BondManageVO> getBondManageList(ExhibitorDTO exhibitorDTO) {
        QueryWrapper<BondManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BondManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Objects.nonNull(exhibitorDTO.getBuilderId()), BondManage::getServiceProviderId, exhibitorDTO.getBuilderId())
                .eq(StrUtil.isNotBlank(exhibitorDTO.getSpaceCode()), BondManage::getSpaceCode, exhibitorDTO.getSpaceCode())
                .eq(StrUtil.isNotBlank(exhibitorDTO.getSiteCode()), BondManage::getSiteCode, exhibitorDTO.getSiteCode())
                .orderByDesc(BondManage::getCreateTime);
        List<BondManage> list = list(queryWrapper);
        List<BondManageVO> bondManageVOList = ConvertUtil.convertList(list, BondManageVO.class);
        return bondManageVOList;
    }

    @Override
    public ExhibitionSettlementVO getVenueBondManageSettlement(ExhibitionSettlementDTO query) {
        // 查询场馆设置的保证金
        BondManageDTO bondManageQuery = new BondManageDTO();
        bondManageQuery.setExhibitionManageId(query.getExhibitionManageId());
        bondManageQuery.setServiceProviderId(query.getCompanyId());
        bondManageQuery.setSystemScene(MenuAffiliationEnum.P_COMPOSITE_VENUE.getCode());
        List<BondManage> bondManageList = listBondManageForSettlement(bondManageQuery);
        if (bondManageList == null || bondManageList.isEmpty()) {
            return null;
        }
        ExhibitionSettlementVO exhibitionSettlementVO = BondManageService.calculateExhibitionSettlement(bondManageList);
        return exhibitionSettlementVO;
    }

    /**
     * 通过服务商id获取保证金集合
     *
     * @param serviceProviderId
     * @return
     */
    @Override
    public List<BondManageVO> getBondManageListByServiceProviderId(Long serviceProviderId) {
        QueryWrapper<BondManage> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BondManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Objects.nonNull(serviceProviderId), BondManage::getServiceProviderId, serviceProviderId)
                .orderByDesc(BondManage::getCreateTime);
        List<BondManage> list = list(queryWrapper);
        List<BondManageVO> bondManageVOList = ConvertUtil.convertList(list, BondManageVO.class);
        return bondManageVOList;
    }

    /**
     * 通过id查询保证金信息
     *
     * @param id
     * @return
     */
    @Override
    public BondManageVO getBondManageVOById(Long id) {
        BondManage bondManage = getById(id);
        BondManageVO bondManageVO = BeanUtil.toBean(bondManage, BondManageVO.class);
        return bondManageVO;
    }

    @Override
    public List<BondManage> listBondManage(BondManageDTO bondManageDTO) {
        QueryWrapper<BondManage> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BondManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(StrUtil.isNotBlank(bondManageDTO.getBelongSystem()), BondManage::getBelongSystem, bondManageDTO.getBelongSystem())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSystemScene()), BondManage::getSystemScene, bondManageDTO.getSystemScene())
                .eq(StrUtil.isNotBlank(bondManageDTO.getOrderNumber()), BondManage::getOrderNumber, bondManageDTO.getOrderNumber())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSpaceCode()), BondManage::getSpaceCode, bondManageDTO.getSpaceCode())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSpaceName()), BondManage::getSpaceName, bondManageDTO.getSpaceName())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSiteCode()), BondManage::getSiteCode, bondManageDTO.getSiteCode())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSiteName()), BondManage::getSiteName, bondManageDTO.getSiteName())
                .eq(bondManageDTO.getExhibitionManageId() != null, BondManage::getExhibitionManageId, bondManageDTO.getExhibitionManageId())
                .eq(bondManageDTO.getServiceProviderId() != null, BondManage::getServiceProviderId, bondManageDTO.getServiceProviderId())
                .eq(bondManageDTO.getExhibitorId() != null, BondManage::getExhibitorId, bondManageDTO.getExhibitorId())
                .in(bondManageDTO.getExhibitorIdList() != null && !bondManageDTO.getExhibitorIdList().isEmpty(), BondManage::getExhibitorId, bondManageDTO.getExhibitorIdList())
        ;
        return list(queryWrapper);
    }

    @Override
    public List<BondManage> listBondManageForSettlement(BondManageDTO bondManageDTO) {
        log.info("listBondManageForSettlement - 查询结算保证金, bondManageDTO={}", bondManageDTO);
        QueryWrapper<BondManage> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(BondManage::getIsDeleted, BusinessConstant.DELETE_NO)
                .ne(BondManage::getOrderStatus, BondManageOrderStatusEnum.CANCEL)
                .ne(BondManage::getOrderStatus, BondManageOrderStatusEnum.NOT_SUBMIT)
                .eq(StrUtil.isNotBlank(bondManageDTO.getBelongSystem()), BondManage::getBelongSystem, bondManageDTO.getBelongSystem())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSystemScene()), BondManage::getSystemScene, bondManageDTO.getSystemScene())
                .eq(StrUtil.isNotBlank(bondManageDTO.getOrderNumber()), BondManage::getOrderNumber, bondManageDTO.getOrderNumber())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSpaceCode()), BondManage::getSpaceCode, bondManageDTO.getSpaceCode())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSpaceName()), BondManage::getSpaceName, bondManageDTO.getSpaceName())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSiteCode()), BondManage::getSiteCode, bondManageDTO.getSiteCode())
                .eq(StrUtil.isNotBlank(bondManageDTO.getSiteName()), BondManage::getSiteName, bondManageDTO.getSiteName())
                .eq(bondManageDTO.getExhibitionManageId() != null, BondManage::getExhibitionManageId, bondManageDTO.getExhibitionManageId())
                .eq(bondManageDTO.getServiceProviderId() != null, BondManage::getServiceProviderId, bondManageDTO.getServiceProviderId())
                .eq(bondManageDTO.getExhibitorId() != null, BondManage::getExhibitorId, bondManageDTO.getExhibitorId())
        ;
        return list(queryWrapper);

    }

    @Override
    public List<BondManage> listVenueBondByServiceProviderId(Long serviceProviderId, Long exhibitionManageId) {
        BondManageDTO query = new BondManageDTO();
        query.setExhibitionManageId(exhibitionManageId);
        query.setServiceProviderId(serviceProviderId);
        query.setSystemScene(MenuAffiliationEnum.P_COMPOSITE_VENUE.getCode());
        return listBondManage(query);
    }

    @Override
    public BondManageVO getVOByOrderNumber(String orderNumber) {
        BondManage bondManage = getByOrderNumber(orderNumber);
        if (bondManage == null) {
            return null;
        }
        return BeanUtil.toBean(bondManage, BondManageVO.class);
    }

    @Override
    public BondManage getByOrderNumber(String orderNumber) {
        log.info("getByOrderNumber - 订单编号查询保证金订单, orderNumber={}", orderNumber);
        BondManageDTO model = new BondManageDTO();
        model.setOrderNumber(orderNumber);
        List<BondManage> list = listBondManage(model);
        if (list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 保存保证金管理
     *
     * @param bondManageDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BondManage saveBondManageInfo(BondManageDTO bondManageDTO) {
        log.info("BondManageServiceImpl +++++ saveBondManageInfo - 保存保证金管理 bondManageDTO={}", JSONObject.toJSON(bondManageDTO));
        // 生成订单号
        if (StrUtil.isBlank(bondManageDTO.getOrderNumber())) {
            String prefix = LocalDateTimeUtil.format(LocalDate.now(), "yyyyMMdd");
            String orderNumber = CreatCode.creatCode(baseMapper, ORDER_NUMBER_FIELD, ORDER_NUMBER_LENGTH, prefix);
            bondManageDTO.setOrderNumber(orderNumber);
        }
        BondManage bondManage = BeanUtil.toBean(bondManageDTO, BondManage.class);
        save(bondManage);
        return bondManage;
    }

    @Override
    public BondManage saveForVenue(BondManageDTO bondManageDTO) {
        bondManageDTO.setOrderStatus(BondManageOrderStatusEnum.SUBMIT);
        bondManageDTO.setOrderTime(LocalDateTime.now());
        BondManage bondManage = saveBondManageInfo(bondManageDTO);
        // 更新违规扣款记录
        violationFineService.updateVenueBondOrderNumber(bondManage.getExhibitionManageId(), bondManage.getServiceProviderId(), bondManage.getOrderNumber());
        // 生成支付系统交易订单
        if (bondManageDTO.getBondAmount() != null && !BigDecimal.ZERO.equals(bondManageDTO.getBondAmount())) {
            saveTransactionOrder(bondManage.getId());
        }
        return bondManage;
    }

    /**
     * 设置保证金金额
     *
     * @param bondManageDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBondManageById(BondManageDTO bondManageDTO) {
        log.info("BondManageServiceImpl +++++ updateBondManageById - 设置保证金金额 bondManageDTO={}", JSONObject.toJSON(bondManageDTO));
        BondManage bondManage = BeanUtil.toBean(bondManageDTO, BondManage.class);
        BondManage manage = getById(bondManage.getId());
        if (Objects.isNull(manage)) {
            throw BizException.wrap(-1, "保证金信息为空");
        }
        if (Objects.nonNull(manage.getBondAmount())) {
            BigDecimal sumAmount = bondManage.getBondAmount().add(manage.getBondAmount());
            bondManage.setBondAmount(sumAmount);
            if (manage.getPayStatus().equals("1")) {
                bondManage.setPayStatus("2");
            }
            BondManage oldEntity = getById(bondManage.getId());
            // 修改预警金额
            DepositWarningDTO depositWarningDTO = new DepositWarningDTO();
            depositWarningDTO.setExhibitionManageId(oldEntity.getExhibitionManageId());
            depositWarningDTO.setServiceProviderId(oldEntity.getServiceProviderId());
            depositWarningDTO.setPrice(sumAmount);
            depositWarningService.updateByExhibition(depositWarningDTO);
        }
        updateById(bondManage);
        // 生成支付系统交易订单
        if (bondManageDTO.getBondAmount() != null && !BigDecimal.ZERO.equals(bondManageDTO.getBondAmount())) {
            saveTransactionOrder(bondManage.getId());
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BondManage updatePayAmount(BondManageDTO bondManageDTO) {
        log.info("updatePayAmount - 更新保证金支付金额, bondManageDTO={}", bondManageDTO);
        BondManage bondManage = getById(bondManageDTO.getId());
        if (Objects.isNull(bondManage)) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        // 保证金已支付金额
        BigDecimal payAmount = bondManage.getPayAmount() == null ? BigDecimal.ZERO : bondManage.getPayAmount();
        BigDecimal refundableAmount = bondManage.getRefundableAmount() == null ? BigDecimal.ZERO : bondManage.getRefundableAmount();
        if (payAmount.compareTo(bondManage.getBondAmount()) >= 0) {
            throw BizException.wrap(-1, "保证金已支付金额大于等于保证金金额，无需支付");
        }
        // 当前准备支付的金额
        BigDecimal nowPayAmount = bondManageDTO.getPayAmount() == null ? BigDecimal.ZERO : bondManageDTO.getPayAmount();
        payAmount = payAmount.add(nowPayAmount);
        refundableAmount = refundableAmount.add(nowPayAmount);
        int compareWithBond = payAmount.compareTo(bondManage.getBondAmount());
        if (compareWithBond == 0) {
            bondManage.setPayStatus(BondManagePayStatusEnum.PAYED.getCode());
            bondManage.setRefundStatus(BondManageRefundStatus.NOT_APPLIED.getCode());
        } else if (compareWithBond < 0) {
            bondManage.setPayStatus(BondManagePayStatusEnum.PARTPAY.getCode());
            bondManage.setRefundStatus(BondManageRefundStatus.NOT_APPLIED.getCode());
        } else {
            throw BizException.wrap(-1, "支付金额超过保证金剩余未支付金额，无法支付");
        }
        bondManage.setPayAmount(payAmount);
        bondManage.setRefundableAmount(refundableAmount);
        updateById(bondManage);
        return bondManage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BondManage updateRefundStatus(BondManageDTO bondManageDTO) {
        log.info("updateRefundStatus - 更新退款状态, bondManageDTO={}", bondManageDTO);
        BondManage bondManage = getByOrderNumber(bondManageDTO.getOrderNumber());
        if (bondManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        bondManage.setRefundStatus(bondManageDTO.getRefundStatus());
        bondManage.setRefundTime(LocalDateTime.now());
        bondManage.setRefundWay(bondManageDTO.getRefundWay());
        // 计算退款金额
        BigDecimal actualRefundAmount = bondManage.getActualRefundAmount() == null ? BigDecimal.ZERO : bondManage.getActualRefundAmount();
        if (bondManageDTO.getActualRefundAmount() != null && BondManageRefundStatus.AUTH_SUCESS.eq(bondManageDTO.getRefundStatus())) {
            actualRefundAmount = actualRefundAmount.add(bondManageDTO.getActualRefundAmount());
            bondManage.setActualRefundAmount(actualRefundAmount);
        }
        updateById(bondManage);
        return bondManage;
    }

    /**
     * 通过服务商id删除设置保证金信息
     *
     * @param serviceProviderId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delBondManageByServiceProviderId(Long serviceProviderId) {
        log.info("delBondManageByServiceProviderId - 通过服务商id删除设置保证金信息, id={}", serviceProviderId);
        UpdateWrapper<BondManage> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(BondManage::getIsDeleted, BusinessConstant.NO).eq(BondManage::getServiceProviderId, serviceProviderId)
                .set(BondManage::getIsDeleted, BusinessConstant.YES);
        return update(updateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delBondManageByServiceProviderId(Long serviceProviderId, Long exhibitionManageId) {
        List<BondManage> bondManageList = listVenueBondByServiceProviderId(serviceProviderId, exhibitionManageId);
        if (bondManageList == null || bondManageList.isEmpty()) {
            return false;
        }
        // 删除保证金订单
        removeByIdsOfLogic(bondManageList);
        // 更新违规扣款记录
        List<String> bondOrderNumberList = bondManageList
                .stream()
                .map(BondManage::getOrderNumber)
                .collect(Collectors.toList());
        violationFineService.cancelByBondOrderNumberList(bondOrderNumberList);
        return true;
    }

    @Override
    public boolean saveTransactionOrder(BondManageDTO bondManageDTO) {
        log.info("saveTransactionOrder - 生成支付系统交易订单, bondManageDTO={}", bondManageDTO);
        TransactionOrderDTO transactionOrderDTO = BondManageService.toTransactionOrder(bondManageDTO);
        return venueManageTransactionOrderService.save(transactionOrderDTO);
    }

    @Override
    public boolean saveTransactionOrder(Long id) {
        BondManage bondManage = getById(id);
        if (bondManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        BondManageDTO bondManageDTO = completeForTransactionOrder(bondManage);
        return saveTransactionOrder(bondManageDTO);
    }

    @Override
    public BondManageDTO completeForTransactionOrder(BondManage bondManage) {
        BondManageDTO bondManageDTO = BeanUtil.toBean(bondManage, BondManageDTO.class);
        bondManageDTO.setPayee(venueManagePayee);
        return bondManageDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int canDeductBond(Long exhibitionId, Long serviceProviderId, BigDecimal shouldDeductAmount) {
        log.info("canDeductBond - 是否可扣除保证金, exhibitionId={}, serviceProviderId={}, shouldDeductAmount={}", exhibitionId, serviceProviderId, shouldDeductAmount);
        // 查询服务商的场馆保证金
        List<BondManage> bondManageList = listVenueBondByServiceProviderId(serviceProviderId, exhibitionId);
        // 没有保证金，则不可扣除
        if (bondManageList == null || bondManageList.isEmpty()) {
            return BusinessConstant.NO;
        }
        BondManage bondManage = bondManageList.get(0);
        // 保证金已取消，不可扣除
        if (BondManageOrderStatusEnum.CANCEL.eq(bondManage.getOrderStatus())) {
            return BusinessConstant.NO;
        }
        return BusinessConstant.YES;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BondManage deductBondAmount(Long exhibitionId, Long serviceProviderId, BigDecimal shouldDeductAmount) {
        log.info("deductBondAmount - 扣除保证金, exhibitionId={}, serviceProviderId={}, shouldDeductAmount={}", exhibitionId, serviceProviderId, shouldDeductAmount);
        List<BondManage> bondManageList = listVenueBondByServiceProviderId(serviceProviderId, exhibitionId);
        if (bondManageList == null || bondManageList.isEmpty()) {
            return null;
        }
        // 更新可退款金额
        BondManage bondManage = bondManageList.get(0);
        return deductBondAmount(bondManage, shouldDeductAmount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BondManage deductBondAmount(String orderNumber, BigDecimal shouldDeductAmount) {
        BondManage bondManage = getByOrderNumber(orderNumber);
        if (bondManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        return deductBondAmount(bondManage, shouldDeductAmount);
    }

    @Override
    public BondManage deductBondAmount(BondManage bondManage, BigDecimal shouldDeductAmount) {
        // 更新可退款金额
        BigDecimal refundableAmount = bondManage.getRefundableAmount() == null ? BigDecimal.ZERO : bondManage.getRefundableAmount();
        refundableAmount = refundableAmount.subtract(shouldDeductAmount);
        bondManage.setRefundableAmount(refundableAmount);
        // 更新已扣除金额
        BigDecimal deductAmount = bondManage.getDeductAmount() == null ? BigDecimal.ZERO : bondManage.getDeductAmount();
        deductAmount = deductAmount.add(shouldDeductAmount);
        bondManage.setDeductAmount(deductAmount);
        updateById(bondManage);
        return bondManage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refundBondManage(Long exhibitionId, Long serviceProviderId, BigDecimal shouldRefundAmount) {
        List<BondManage> bondManageList = listVenueBondByServiceProviderId(serviceProviderId, exhibitionId);
        if (bondManageList == null || bondManageList.isEmpty()) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        BondManage bondManage = bondManageList.get(0);
        return refundBondManage(bondManage, shouldRefundAmount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refundBondManage(String orderNumber, BigDecimal shouldRefundAmount) {
        BondManage bondManage = getByOrderNumber(orderNumber);
        if (bondManage == null) {
            throw BizException.wrap(VenueServiceExceptionCode.BOND_MANAGE_NOT_EXIST);
        }
        return refundBondManage(bondManage, shouldRefundAmount);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean refundBondManage(BondManage bondManage, BigDecimal shouldRefundAmount) {
        log.info("refundBondManage - 退还保证金, bondManage={}, shouldRefundAmount={}", bondManage, shouldRefundAmount);
        // 更新可退款金额
        BigDecimal refundableAmount = bondManage.getRefundableAmount() == null ? BigDecimal.ZERO : bondManage.getRefundableAmount();
        refundableAmount = refundableAmount.add(shouldRefundAmount);
        bondManage.setRefundableAmount(refundableAmount);
        // 更新已扣除金额
        BigDecimal deductAmount = bondManage.getDeductAmount() == null ? BigDecimal.ZERO : bondManage.getDeductAmount();
        deductAmount = deductAmount.subtract(shouldRefundAmount);
        bondManage.setDeductAmount(deductAmount);
        return updateById(bondManage);
    }


    @Override
    public boolean applyBondManageRefund(BondManageDTO bondManageDTO) {
        log.info("applyBondManageRefund - 发起退款，bondManageDTO={}", bondManageDTO);
        BigDecimal payAmount = bondManageDTO.getPayAmount();
        String payStatus = bondManageDTO.getPayStatus();
        if (!BondManagePayStatusEnum.PAYED.getCode().equals(payStatus) && !BondManagePayStatusEnum.PARTPAY.getCode().equals(payStatus)) {
            log.info("acceptBondManage - 不是已付款，部分付款，无需退款");
            return false;
        }
        if (!BondManageRefundStatus.NOT_APPLIED.eq(bondManageDTO.getRefundStatus()) && !ServiceOrderRefundStatus.AUTH_FAIL.eq(bondManageDTO.getRefundStatus())) {
            log.warn("acceptApplyRefund - 不是未申请退款的，退款申请驳回的无需退款");
            // 不是未申请退款的，退款申请驳回的无需退款
            return false;
        }
        if (payAmount.equals(BigDecimal.ZERO)) {
            log.warn("acceptBondManage - 支付金额为0，无需退款");
            return false;
        }
        // 更新订单退款状态为已申请
//        BondManageDTO applyRefundDTO = new BondManageDTO();
//        applyRefundDTO.setOrderNumber(bondManageDTO.getOrderNumber());
//        applyRefundDTO.setRefundStatus(ServiceOrderRefundStatus.APPLIED.getCode());
//        updateRefundStatus(applyRefundDTO);
        // 发起支付系统的退款申请
        acceptApplyRefund(bondManageDTO);
        return true;
    }

    @Override
    public boolean acceptApplyRefund(BondManageDTO bondManageDTO) {
        log.info("applyBondManageRefund - 发起退款申请, bondManageDTO={}", bondManageDTO);
        // 发起支付中心退款
        ApplyRefundDTO applyRefundDTO = new ApplyRefundDTO();
        applyRefundDTO.setCutomerId(bondManageDTO.getServiceProviderId());
        applyRefundDTO.setCutomerName(bondManageDTO.getServiceProviderName());
        applyRefundDTO.setRefundApplyAmount(bondManageDTO.getPayAmount());
        applyRefundDTO.setExhibitionId(bondManageDTO.getExhibitionManageId());
        applyRefundDTO.setExhibitionName(bondManageDTO.getExhibitionManageName());
        //  退款人联系方式
        Long userId = ContextUtil.getUserId();
        if (userId != null) {
            UserAccountVo userAccountVo = venueManageUserAccountService.findSimpleById(userId);
            applyRefundDTO.setApplicantId(userId);
            applyRefundDTO.setApplicantName(userAccountVo.getRealName());
            applyRefundDTO.setApplicantConcat(userAccountVo.getMobile());
        }
        applyRefundDTO.setBusinessId(bondManageDTO.getId());
        applyRefundDTO.setBusinessNum(bondManageDTO.getOrderNumber());
        applyRefundDTO.setBusinessType(ApplyRefundBusinessTypeEnum.B.getCode());
        applyRefundDTO.setRefundClassify(RefundClassifyEnum.ORDER_CANCEL.getCode());
        applyRefundDTO.setSystemCode(bondManageDTO.getSystemScene());
        return venueManageApplyRefundService.acceptApplyRefund(applyRefundDTO);
    }

}
